package org.jsets.fastboot.httputils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
public class HttpClient {

	private static HttpClient getInstance() {
		return SingleHolder.singleton;
	}

	private static class SingleHolder {
		private static final HttpClient singleton = new HttpClient();
	}

	private final OkHttpClient okHttpClient;

	private HttpClient() {
		this.okHttpClient = new OkHttpClient.Builder()
				.sslSocketFactory(sslSocketFactory(), x509TrustManager())
				.retryOnConnectionFailure(false) // 网络连接失败重新请求
				.connectionPool(new ConnectionPool(1500, 5, TimeUnit.MINUTES))
				.connectTimeout(20, TimeUnit.SECONDS) // 网络连接超时时间
				.readTimeout(20, TimeUnit.SECONDS)
				.writeTimeout(20, TimeUnit.SECONDS)
				.build();
	}

	protected X509TrustManager x509TrustManager() {
		return new X509TrustManager() {
			@Override
			public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return new X509Certificate[0];
			}
		};
	}

	protected SSLSocketFactory sslSocketFactory() {
		try {
			SSLContext sslContext = SSLContext.getInstance("TLS");// 信任任何链接
			sslContext.init(null, new TrustManager[] { x509TrustManager() }, new SecureRandom());
			return sslContext.getSocketFactory();
		} catch (NoSuchAlgorithmException e) {
			log.error(e.getMessage(), e);
		} catch (KeyManagementException e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	public static OkHttpClient getOkHttpClient() {
		return getInstance().okHttpClient;
	}
	
//	public static NoBodyRequest delete(String url) {
//		return new NoBodyRequest(url, Method.DELETE);
//	}
//	
//	public static JsonRequest post(String url) {
//		return new JsonRequest(url, Method.POST);
//	}
//	
//	public static JsonRequest put(String url) {
//		return new JsonRequest(url, Method.PUT);
//	}
	
//	public static BodyActuator formPost(String url) {
//		return new BodyActuator(url, Method.POST);
//	}
//	
//	public static BodyActuator formPut(String url) {
//		return new BodyActuator(url, Method.PUT);
//	}
	
	public static HttpRequest get(String url,Object... parameters) {
		HttpRequest r = new HttpRequest(completeUrl(url, parameters));
		r.get();
		return r;
	}
	
	public static HttpRequest delete(String url,Object... parameters) {
		HttpRequest r = new HttpRequest(completeUrl(url, parameters));
		r.delete();
		return r;
	}
	
	public static BodyHttpRequest post(String url,Object... parameters) {
		BodyHttpRequest r = new BodyHttpRequest(completeUrl(url, parameters));
		r.post();
		return r;
	}

	private static String completeUrl(String url, Map<String, Object> parameters) {
		StringBuilder sb = new StringBuilder(url);
		if (parameters != null && parameters.keySet().size() > 0) {
			boolean firstFlag = true;
			Iterator<Map.Entry<String, Object>> iterator = parameters.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, Object> entry = iterator.next();
				if (firstFlag) {
					sb.append("?" + entry.getKey() + "=" + entry.getValue());
					firstFlag = false;
				} else {
					sb.append("&" + entry.getKey() + "=" + entry.getValue());
				}
			}
		}
		return sb.toString();
	}

	private static String completeUrl(String url, Object[] parameters) {
		if (parameters != null && parameters.length > 0) {
			StringBuilder sb = new StringBuilder();
			int index = 0;
			for(char s : url.toCharArray()) {
				if('?'==s) {
					sb.append(parameters[index]);
					index++;
				}else {
					sb.append(s);
				}
			}
			return sb.toString();
		}
		return url;
	}

}